package app.oa.dao;

import java.io.Serializable;
import java.util.List;
import java.util.Map;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Restrictions;

public abstract class BaseDao {
	private SessionFactory sessionFactory;

	public void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}
	
	protected Session getSession() {
		return sessionFactory.getCurrentSession();
	}
	
	@SuppressWarnings("unchecked")
	protected <T> T get(Class<T> clazz, int id) {
		return (T) getSession().get(clazz, id);
	}
	
	/**
	 * 通过参数列表查找指定类的单个对象
	 * @param clazz
	 * 			要查找的类
	 * @param map
	 * 			以键值对形式存放的参数列表，键为属性名，值为属性值
	 * @return
	 * 			查找到的实体，若不存在则返回null
	 */
	@SuppressWarnings("unchecked")
	protected <T> T getWithParam(Class<T> clazz, Map<String, Object> map) {
		return (T) getSession().createCriteria(clazz)
			.add(Restrictions.allEq(map))
			.uniqueResult();
	}
	
	/**
	 * 持久化某个对象
	 * @param t
	 * 			要持久化的对象
	 * @return
	 * 			结果
	 */
	protected <T> Serializable save(T t) {
		return getSession().save(t);
	}
	
	/**
	 * 更新某个对象
	 * @param t
	 * 			要更新的对象
	 */
	protected <T> void update(T t) {
		getSession().update(t);
	}
	
	/**
	 * 删除某个实体对象
	 * @param t
	 * 			要删除的对象
	 */
	protected <T> void delete(T t) {
		getSession().delete(t);
	}
	
	/**
	 * 统计指定实体类在数据库中的对象数量
	 * @param clazz
	 * 			要统计的类
	 * @return
	 * 			数量
	 */
	protected <T> int count(Class<T> clazz) {
		Query query = getSession().createQuery("select count(*) from ?");
		query.setParameter(0, clazz.getSimpleName());
		return ((Number)query.uniqueResult()).intValue();
	}
	
	/**
	 * 获得指定实体的列表，并实现分页
	 * @param clazz
	 * 			要查找的类
	 * @param first
	 * 			分页查询的起始位置
	 * @param number
	 * 			分页查询的查找数量
	 * @return
	 * 			查找到的列表
	 */
	@SuppressWarnings("unchecked")
	protected <T> List<T> getList(Class<T> clazz, int first, int number) {
		return getSession().createCriteria(clazz)
				.setFirstResult(first).setMaxResults(number).list();
	}
	
	/**
	 * 通过参数列表查找指定类的对象列表，并实现分页查询
	 * @param clazz
	 * 			要查找的类
	 * @param first
	 * 			分页查询的起始位置
	 * @param number
	 * 			分页查询的查找数量
	 * @param map
	 * 			以键值对形式存放的参数列表，键为属性名，值为属性值
	 * @return
	 * 			查找到的列表
	 */
	@SuppressWarnings("unchecked")
	protected <T> List<T> getListWithParam(Class<T> clazz, int first, int number, Map<String, Object> map) {
		return getSession().createCriteria(clazz)
			.add(Restrictions.allEq(map))
			.setFirstResult(first)
			.setMaxResults(number)
			.list();
	}
}
